package com.design.found.factory.abstractfactory;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用反射工具类
 *
 * @author cg
 * @date 2019-09-19 14:39
 * @since 4.0
 */
@Component
public class ReflectionUtils {

    @Autowired
    WebApplicationContext applicationContext;

    public static void main(String[] args) {
        Red object =(Red)getObj("com.design.found.factory.abstractfactory.Red");
        object.s();
    }
    /**
     * 获取类并启动类实例（调用不涉及注入的普通类）
     *
     * @param pathName pathName
     * @return Object 类对象
     * @author cg
     * @date 2019-09-19 14:41
     * @since 4.0
     */
    public static Object getObj(String pathName) {
        try {
            Class<?> cls = Class.forName(pathName);
            Object o = cls.newInstance();
            return o;
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据方法名调用指定对象的方法
     *
     * @param object     要调用方法的对象
     * @param methodName 要调用的方法名
     * @param args       参数对象数组
     * @return Object
     * @author cg
     * @date 2019-09-19 14:58
     * @since 4.0
     */
    public static Object invoke(Object object, String methodName, Object... args) {
        Object result = null;
        Class<? extends Object> clazz = object.getClass();
        Method queryMethod = getMethod(clazz, methodName, args);
        if (queryMethod != null) {
            try {
                result = queryMethod.invoke(object, args);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } else {
            try {
                throw new NoSuchMethodException(clazz.getName() + " 类中没有找到 " + methodName + " 方法。");
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 根据方法名和参数对象查找方法
     *
     * @param clazz      clazz
     * @param methodName 方法名
     * @param args       参数实例数据
     * @return Method
     * @author cg
     * @date 2019-09-19 14:58
     * @since 4.0
     */
    public static Method getMethod(Class<? extends Object> clazz, String methodName, Object[] args) {
        Method queryMethod = null;
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                // 判断传递的参数个数是否与方法参数的个数相同，可能存在重载的方法
                if (parameterTypes.length == args.length) {
                    boolean isSameMethod = true;
                    // 判断传递的参数类型是否与方法参数类型相同
                    for (int i = 0; i < parameterTypes.length; i++) {
                        Object arg = args[i];
                        if (arg == null) {
                            arg = "";
                        }
                        if (!parameterTypes[i].equals(args[i].getClass())) {
                            isSameMethod = false;
                        }
                    }
                    if (isSameMethod) {
                        queryMethod = method;
                        break;
                    }
                }
            }
        }
        return queryMethod;
    }


}